package com.bootdo.clouddo.utils.book;

import com.bootdo.clouddo.utils.StringUtils;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.net.ssl.HttpsURLConnection;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class HttpUtils {
	
	static Logger logger = LoggerFactory.getLogger("xbky.util.HttpUtils");
    
	private static CloseableHttpClient httpclient = HttpClients.createDefault();       //创建一个客户端
    
    // User-Agent
 	public static final String USERAGENT_FIREFOX = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0";  
 	public static final String USERAGENT_IE = "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko";  
 	
 	private static BasicCookieStore cookieStore;
	private static HttpPost post;
    
    public static StringBuffer httpsRequest(String requestUrl, String requestMethod, String output) throws IOException {
        URL url = new URL(requestUrl);
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setUseCaches(false);
        connection.setRequestMethod(requestMethod);
        if (null != output) {
            OutputStream outputStream = connection.getOutputStream();
            outputStream.write(output.getBytes("UTF-8"));
            outputStream.close();
        }
        // 从输入流读取返回内容
        InputStream inputStream = connection.getInputStream();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String str = null;
        StringBuffer buffer = new StringBuffer();
        while ((str = bufferedReader.readLine()) != null) {
            buffer.append(str);
        }
        bufferedReader.close();
        inputStreamReader.close();
        inputStream.close();
        inputStream = null;
        connection.disconnect();
        return buffer;
    }

	public static HttpResult doGet(String url, String charset) throws Exception {
		return doGet(url, new HashMap<>(), new HashMap<>(), charset);
	}
	
	public static HttpResult doGet(String url, Map<String, String> headers, Map<String, String> params, String charset) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException, IOException {

		if (url == null|| url.equals("")) {
			return null;
		}

		SSLContextBuilder builder = new SSLContextBuilder();
		builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
		cookieStore = new BasicCookieStore();
		CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore)
				.setSSLSocketFactory(sslsf).build();
		HttpResult result = null;
		try {

			url = url + "?" + parseParams(params);
			HttpGet httpget = new HttpGet(url);
			httpget.setHeaders(parseHeader(headers));
			httpget.setConfig(RequestConfig.DEFAULT);
			CloseableHttpResponse response = httpclient.execute(httpget);
			try {
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					result = new HttpResult();
					result.setCookies(cookieStore.getCookies());
					result.setStatusCode(response.getStatusLine().getStatusCode());
					result.setHeaders(response.getAllHeaders());
					if(StringUtils.isNoneBlank(charset)) {
						result.setBody(EntityUtils.toString(entity, charset));
					}else {
						result.setBody(EntityUtils.toString(entity));
					}
				}

			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}

		return result;
		
	}

	public static HttpResult doPost(String url, Map<String, String> headers, Map<String, String> postData, String encoding) throws Exception {

		if (url == null|| url.equals("")) {
			return null;
		}
		if (encoding == null|| encoding.equals("")) {
			encoding = "utf-8";
		}
		
		SSLContextBuilder builder = new SSLContextBuilder();
		builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
		cookieStore = new BasicCookieStore();
		CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore)
				.setSSLSocketFactory(sslsf).build();

		post = new HttpPost(url);
		List<NameValuePair> list = new ArrayList<NameValuePair>();
		for (String tmp : postData.keySet()) {
			list.add(new BasicNameValuePair(tmp, postData.get(tmp)));
		}
		post.setEntity(new UrlEncodedFormEntity(list, encoding));
		post.setHeaders(parseHeader(headers));

		CloseableHttpResponse response = httpClient.execute(post);
		HttpEntity entity = response.getEntity();

		HttpResult result = new HttpResult();
		result.setCookies(cookieStore.getCookies());
		result.setStatusCode(response.getStatusLine().getStatusCode());
		result.setHeaders(response.getAllHeaders());
		result.setBody(EntityUtils.toString(entity, encoding));

		close(entity, response);

		return result;
	}

	public static String parseParams(Map<String, String> params) {
		if (params == null || params.isEmpty()) {
			return "";
		}

		StringBuffer sb = new StringBuffer();
		for (String key : params.keySet()) {
			sb.append(key + "=" + params.get(key) + "&");
		}
		return sb.substring(0, sb.length() - 1);

	}

	private static Header[] parseHeader(Map<String, String> headers) {
		if (headers == null || headers.isEmpty()) {
			return getDefaultHeaders();
		}

		Header[] retHeader = new BasicHeader[headers.size()];
		int i = 0;
		for (String str : headers.keySet()) {
			retHeader[i++] = new BasicHeader(str, headers.get(str));
		}
		return retHeader;
	}

	private static Header[] getDefaultHeaders() {
		Header[] headers = new BasicHeader[3];
		headers[0] = new BasicHeader("User-Agent", USERAGENT_IE);
		headers[1] = new BasicHeader("Accept-Encoding", "gzip, deflate");
		headers[2] = new BasicHeader("Accept-Language", "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3");
		return headers;
	}

	private static void close(HttpEntity entity, CloseableHttpResponse response) {
		try {
			if (entity != null) {
				InputStream input = entity.getContent();
				input.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				//e.printStackTrace();
			}
		}
	}

	
	/**
	 * 下载文件
	 * @param url 下载文件的链接
	 * @param destFile 包含路径的目标文件名
	 * @param headers 请求头
	 * @return 
	 */
	public HttpResult downloadFile(String url, String destFile, Map<String, String> headers) throws Exception {
		
		SSLContextBuilder builder = new SSLContextBuilder();
		builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
		BasicCookieStore cookieStore = new BasicCookieStore();
		CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).setSSLSocketFactory(sslsf).build();
		
		HttpGet get = new HttpGet(url);
		get.setHeaders(parseHeader(headers));
		InputStream input = null;
		CloseableHttpResponse response = null;
		HttpResult result = null;
		
		try {
			response = httpclient.execute(get);
			HttpEntity entity = response.getEntity();
			input = entity.getContent();
			File file = new File(destFile);
			
			FileOutputStream fos = new FileOutputStream(file);
			int len = -1;
			byte[] tmp = new byte[1024];
			while((len=input.read(tmp)) != -1) {
				fos.write(tmp, 0, len);
			}
			fos.flush();
			fos.close();
			
			result = new HttpResult();
			result.setCookies(cookieStore.getCookies());
			result.setStatusCode(response.getStatusLine().getStatusCode());
			result.setHeaders(response.getAllHeaders());
			result.setBody(EntityUtils.toString(entity, Consts.UTF_8));
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(input != null) {
					input.close();
				}
				if(response != null) {
					response.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}
	
	public static void setHeader(HttpGet request) {
		//request.setHeader("Connection", "keep-alive");
        //request.setHeader("Accept-Encoding", "gzip, deflate");
        //request.setHeader("Content-Type", "application/json; charset=gb2312");
        //request.setHeader("Accept", "application/json, text/javascript, */*; q=0.01");
        //request.setHeader("Accept-Charset", "UTF-8,utf-8;q=0.7,*;q=0.7");  
        //request.setHeader("Accept-Language", "zh-cn,zh;q=0.5");
        // request.setHeader("Cookie", "JSESSIONID=AB2C0102D162499605695ECCF6C1F5EC; _ga=GA1.3.945921650.1565495158; zg_did=%7B%22did%22%3A%20%2216d686d0d333-06675ac41c23ee-1d3d6b55-1aeaa0-16d686d0d35a83%22%7D; _ga=GA1.4.945921650.1565495158; __utmz=65168252.1569462118.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utma=229973332.945921650.1565495158.1572261516.1572261516.1; __utmz=229973332.1572261516.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); zg_90dc219b89ee40d99689b0ed4befbe51=%7B%22sid%22%3A%201572528925015%2C%22updated%22%3A%201572528947541%2C%22info%22%3A%201572528925020%2C%22superProperty%22%3A%20%22%7B%7D%22%2C%22platform%22%3A%20%22%7B%7D%22%2C%22utm%22%3A%20%22%7B%7D%22%2C%22referrerDomain%22%3A%20%22yz.chsi.com.cn%22%2C%22landHref%22%3A%20%22https%3A%2F%2Fxz.chsi.com.cn%2Fsurvey%2Findex.action%22%2C%22cuid%22%3A%20%22e7d1e38bb9a5d89fb32bbe75d212182c%22%7D; acw_tc=2760826515759719309473106e6ef75658fac1a5ee4aaa69533456d6f9e0a7; __utma=65168252.945921650.1565495158.1569462118.1577173959.2; aliyungf_tc=AQAAAP25M1vKbQMATlbxcl+rWHZG5XjU; XSRF-CCKTOKEN=ee12cac8205b77f97bdf17a27bed06d0; CHSICC_CLIENTFLAGYZ=e68bdddc3b11eb1d5775a29b260764af; CHSICC_CLIENTFLAGCHSI=60249618f504ea500b03b52cc74a9807; _gid=GA1.3.11915385.1578279818; CHSICC_CLIENTFLAGZSML=de3901ac561c306945606f900cc38fa4; zg_14e129856fe4458eb91a735923550aa6=%7B%22sid%22%3A%201578303495112%2C%22updated%22%3A%201578303501998%2C%22info%22%3A%201578303495115%2C%22superProperty%22%3A%20%22%7B%7D%22%2C%22platform%22%3A%20%22%7B%7D%22%2C%22utm%22%3A%20%22%7B%7D%22%2C%22referrerDomain%22%3A%20%22www.baidu.com%22%2C%22landHref%22%3A%20%22https%3A%2F%2Fwww.chsi.com.cn%2F%22%7D; CHSICC_CLIENTFLAGAPPLY=0a02dad5b472591b3e1e331f80c14220; _gid=GA1.4.11915385.1578279818; JSESSIONID=90759C379A9467932E8D21A98BEE582C; zg_adfb574f9c54457db21741353c3b0aa7=%7B%22sid%22%3A%201578398589943%2C%22updated%22%3A%201578398640471%2C%22info%22%3A%201578299151154%2C%22superProperty%22%3A%20%22%7B%7D%22%2C%22platform%22%3A%20%22%7B%7D%22%2C%22utm%22%3A%20%22%7B%7D%22%2C%22referrerDomain%22%3A%20%22yz.chsi.com.cn%22%2C%22landHref%22%3A%20%22https%3A%2F%2Faccount.chsi.com.cn%2Fpassport%2Flogin%3Fentrytype%3Dyzgr%26service%3Dhttps%253A%252F%252Fyz.chsi.com.cn%252Fapply%252Fj_spring_cas_security_check%22%2C%22cuid%22%3A%20%22e7d1e38bb9a5d89fb32bbe75d212182c%22%7D");
        //request.setHeader("Host", "https://movie.douban.com");  
        //request.setHeader("refer", "https://movie.douban.com");
        //request.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2");
	}

	/**
     * 下载页面
     */
    public static String downloadPage(String url) throws Exception {
    	//logger.info("=========>current_download_url:"+url);
    	//System.out.println("=========>getting:"+url);
        String htmlString = "";         //定义返回的String变量
        Thread.sleep(getRandom(100,300));
        HttpGet request = new HttpGet(url); //请求资源
        //設置httpGet的头部參數信息   
        setHeader(request);
        CloseableHttpResponse response = httpclient.execute(request);           //得到回应
        try {
            HttpEntity entity = response.getEntity();                   //获得Entity对象
            htmlString = EntityUtils.toString(entity);                  //将Entity对象转化为字符串
            EntityUtils.consume(entity);                                //销毁对象
        }catch (Exception e) {
        	e.printStackTrace();
        } finally {
            response.close(); 
        }
        return htmlString;

    }
    
    /**
     * 下载页面
     */
    public static String downloadPageWithCharset(String url, String charset, String modal) throws Exception {
    	//logger.info("=========>current_download_url:"+url);
    	//System.out.println("=========>getting:"+url);
        String htmlString = "";         //定义返回的String变量
        Thread.sleep(getRandom(100,300));
        long before = System.nanoTime();
        if("DEBUG".equalsIgnoreCase(modal)){
        	System.out.print("url:["+url+"] beginning-->");
        }
        HttpGet request = new HttpGet(url); //请求资源
        //設置httpGet的头部參數信息   
        setHeader(request);
        CloseableHttpResponse response = httpclient.execute(request);           //得到回应
        try {
            HttpEntity entity = response.getEntity();                   //获得Entity对象
            if("DEBUG".equalsIgnoreCase(modal)){
            	System.out.println("end[耗时："+(System.nanoTime()-before)/1000000+"ms]");
            }
            htmlString = EntityUtils.toString(entity, charset);                  //将Entity对象转化为字符串
            EntityUtils.consume(entity);                                //销毁对象
        }catch (Exception e) {
        	e.printStackTrace();
        } finally {
            response.close(); 
        }
        return htmlString;

    }
    
    /**
     * 下载页面
     */
    public static String downloadPageWithCharset(String url, String charset) throws Exception {
    	//logger.info("=========>current_download_url:"+url);
    	//System.out.println("=========>getting:"+url);
        String htmlString = "";         //定义返回的String变量
        //Thread.sleep(getRandom(100,500));
        long before = System.nanoTime();
        System.out.print("url:["+url+"] beginning-->");
        HttpGet request = new HttpGet(url); //请求资源
		//setHeader(request);
        CloseableHttpResponse response = httpclient.execute(request);           //得到回应
        try {
            HttpEntity entity = response.getEntity();                   //获得Entity对象
            System.out.println("end[耗时："+(System.nanoTime()-before)/1000000+"ms]");
            htmlString = EntityUtils.toString(entity, charset);                  //将Entity对象转化为字符串
            EntityUtils.consume(entity);                                //销毁对象
        }catch (Exception e) {
        	e.printStackTrace();
        } finally {
            response.close(); 
        }
        return htmlString;

    }
    
    /**
     * 下载页面
     */
    public static String downloadPageWithCharset(String url, Map<String, String> postData, String charset, RequestMethod method) throws Exception {
        Thread.sleep(getRandom(100,500));
        System.out.print("url:["+url+"] beginning-->");
        HttpResult result = null;
        if(method.compareTo(RequestMethod.POST) == 0) {
        	result = doPost(url, null, postData, charset);
        	return result.getBody();
        }else {
        	result = doGet(url, null, postData, charset);
        	return result.getBody();
        }

    }
    
    public static int getRandom(int begin, int end){
    	return (int)(Math.random()*begin)+(end-begin);
    }
    
    public static boolean isAjaxRequest(HttpServletRequest request){
		String header = request.getHeader("X-Requested-With");
		boolean isAjax = "XMLHttpRequest".equals(header) ? true:false;
		return isAjax;
	}
}
